package com.example.library_demo.service.impl;

import com.example.library_demo.dto.circulation.LendBookDTO;
import com.example.library_demo.dto.circulation.MyBorrowDTO;
import com.example.library_demo.dto.circulation.ReturnBookDTO;
import com.example.library_demo.entity.Book;
import com.example.library_demo.entity.Card;
import com.example.library_demo.entity.Circulation;
import com.example.library_demo.exception.BizException;
import com.example.library_demo.mapper.CirculationMapper;
import com.example.library_demo.service.IBookService;
import com.example.library_demo.service.ICardService;
import com.example.library_demo.service.ICirculationService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindException;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author Eric
 * @since 2024-11-27
 */
@Service
public class CirculationServiceImpl extends ServiceImpl<CirculationMapper, Circulation> implements ICirculationService {

    @Autowired
    private IBookService bookService;
    @Autowired
    private ICardService cardService;

    @Override
    public List<MyBorrowDTO> myBorrowList(Long userId) {
        return baseMapper.selectMyBorrowByUserIdAndCirculationId(userId);
    }

    @Override
    @Transactional
    public Boolean lendBooks(Long userId, LendBookDTO lendBookDTO) {
        Card card = cardService.getById(lendBookDTO.getCardId());
        Book book = bookService.getById(lendBookDTO.getBookId());


        if (book.getCount() < lendBookDTO.getLendCount()) {
            throw new BizException("库存不足~");
        }
        if (book.getStatus() != 1) {
            throw new BizException("此书不能借~");
        }

        BigDecimal totalDeposit = book.getDeposit().multiply(new BigDecimal(lendBookDTO.getLendCount()));
        int comparisonResult = card.getBalance().compareTo(totalDeposit);
        if (comparisonResult >= 0) {
            // enough money
            Circulation c = new Circulation();
            c.setDeposit(totalDeposit);
            c.setBookId(book.getBookId());
            c.setCardId(card.getCardId());
            c.setUserId(userId);
            c.setLendCount(lendBookDTO.getLendCount());
            c.setReturnDate(lendBookDTO.getLendDate());
            c.setStatus(0);
            super.save(c);

            card.setBalance(card.getBalance().subtract(totalDeposit));
            cardService.updateById(card);

            book.setCount(book.getCount() - lendBookDTO.getLendCount());
            bookService.updateById(book);
            return true;
        }
        throw new BizException("押金不足~");
    }

    @Override
    public BigDecimal returnBooks(Long userId, ReturnBookDTO lendBookDTO) {
        Card card = cardService.getById(lendBookDTO.getCardId());
        Book book = bookService.getById(lendBookDTO.getBookId());
        Circulation circulation = getById(lendBookDTO.getCirculationId());
        if(null == circulation){
            throw new BizException("没找到出借记录~");
        }
        LocalDateTime actualReturnDate = LocalDateTime.now();
        int days = Period.between(circulation.getLendDate().toLocalDate(), actualReturnDate.toLocalDate()).getDays();
        BigDecimal totalPay = book.getPrice().multiply(new BigDecimal(days));
        BigDecimal needToPay = new BigDecimal(0);
        if(circulation.getDeposit().compareTo(totalPay)>=0){
            //circulation
            BigDecimal returnDeposit = circulation.getDeposit().subtract(totalPay);
            circulation.setReturnDeposit(returnDeposit);
            //card
            card.setBalance(card.getBalance().add(returnDeposit));
        }else {
            needToPay = totalPay.multiply(circulation.getDeposit());
            circulation.setReturnDeposit(new BigDecimal(0));
            if(card.getBalance().compareTo(needToPay)>=0){
                needToPay = new BigDecimal(0);
                //card
                card.setBalance(card.getBalance().multiply(needToPay));
            }else {
                card.setBalance(new BigDecimal(0));
            }
        }
        circulation.setActualReturnDate(LocalDateTime.now());
        circulation.setStatus(1);
        super.updateById(circulation);

        book.setCount(book.getCount()+ lendBookDTO.getLendCount());
        bookService.updateById(book);

        cardService.updateById(card);

        return needToPay;
    }
}
